package com.hay.pay.util;

import lombok.extern.slf4j.Slf4j;

import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.StringWriter;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.cert.*;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
import java.util.Date;

/**
 * 证书工具
 *
 * @author LiMouRen
 * @date 2024/02/02 15:24
 */
@Slf4j
public class CertificateUtil {


    /**
     * 获取私钥
     * @param privateKeyStr 私钥字符串
     */
    public static PrivateKey loadPrivateKey(String privateKeyStr) {
        privateKeyStr = privateKeyStr.replace("-----BEGIN PRIVATE KEY-----", "")
                .replace("-----END PRIVATE KEY-----", "")
                .replaceAll("\\s+", "");
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePrivate(new PKCS8EncodedKeySpec(Base64.getDecoder().decode(privateKeyStr.getBytes(StandardCharsets.UTF_8))));
        } catch (NoSuchAlgorithmException var2) {
            throw new RuntimeException("当前Java环境不支持RSA", var2);
        } catch (InvalidKeySpecException var3) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    /**
     * 获取公钥
     * @param publicKeyStr 公钥字符串
     */
    public static PublicKey loadPublicKey(String publicKeyStr) {
        publicKeyStr = publicKeyStr.replace("-----BEGIN PUBLIC KEY-----", "")
                .replace("-----END PUBLIC KEY-----", "")
                .replaceAll("\\s+", "");
        try {
            KeyFactory kf = KeyFactory.getInstance("RSA");
            return kf.generatePublic(new X509EncodedKeySpec(Base64.getDecoder().decode(publicKeyStr.getBytes(StandardCharsets.UTF_8))));
        } catch (NoSuchAlgorithmException var2) {
            throw new RuntimeException("当前Java环境不支持RSA", var2);
        } catch (InvalidKeySpecException var3) {
            throw new RuntimeException("无效的密钥格式");
        }
    }

    /**
     * 获取证书
     *
     * @param inputStream 证书文件
     * @return 证书
     */
    public static X509Certificate getCertificate(InputStream inputStream) {
        try {
            CertificateFactory cf = CertificateFactory.getInstance("X509");
            X509Certificate cert = (X509Certificate) cf.generateCertificate(inputStream);
            cert.checkValidity();
            return cert;
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateException e) {
            throw new RuntimeException("无效的证书", e);
        }
    }

    /**
     * 获取证书
     *
     * @param certificate 证书
     * @return {@link X509Certificate} 获取证书
     */
    public static X509Certificate getCertificate(String certificate) {
        return getCertificate(new ByteArrayInputStream(certificate.getBytes()));
    }

    /**
     * 获取证书公钥
     *
     * @param certificate 证书
     * @return 证书公钥字符串
     */
    public static String getCertificatePublicKey(String certificate) {
        try {
            X509Certificate cert = getCertificate(new ByteArrayInputStream(certificate.getBytes()));
            cert.checkValidity();
            PublicKey publicKey = cert.getPublicKey();
            byte[] publicKeyByte = Base64.getEncoder().encode(publicKey.getEncoded());
            String publicKeyStr = new String(publicKeyByte);
            StringWriter publicKeyWriter = new StringWriter();
            publicKeyWriter.write("-----BEGIN PUBLIC KEY-----\n");
            publicKeyWriter.write(insertStringEveryIndexChars(publicKeyStr,64,"\n"));
            publicKeyWriter.write("\n-----END PUBLIC KEY-----");
            return publicKeyWriter.toString();
        } catch (CertificateNotYetValidException e) {
            throw new RuntimeException("证书尚未生效", e);
        } catch (CertificateExpiredException e) {
            throw new RuntimeException("证书已过期", e);
        }
    }

    /**
     * 每隔index位置插入字符
     * @param str 原字符串
     * @param insertStr 插入的字符
     * @param index 每隔index位置
     */
    public static String insertStringEveryIndexChars(String str, int index, String insertStr) {
        StringBuilder sb = new StringBuilder(str);
        int insertLen = insertStr.length();
        while (index < sb.length()) {
            sb.insert(index, insertStr);
            index += (64 + insertLen);
        }
        return sb.toString();
    }

    /**
     * 获取证书序列号
     *
     * @param certificate 证书
     * @return 证书序列号
     */
    public static String getCertificateSerialNumber(String certificate) {
        BigInteger serialNumber = getCertificate(certificate).getSerialNumber();
        // 十进制转十六进制，左补零
        String serial = String.format("%" + 20 + "s", serialNumber.toString(16)).replace(' ', '0');
        return serial.toUpperCase();
    }

    /**
     * 获取证书过期时间
     *
     * @param certificate 证书
     * @return 证书序列号
     */
    public static Date getCertificateExpireDate(String certificate) {
        return getCertificate(certificate).getNotAfter();
    }

}